package com.brillilab.service.core.system.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.brillilab.common.alioss.OssFileEnum;
import com.brillilab.common.alioss.OssUtils;
import com.brillilab.common.utils.FileTypeUtil;
import com.brillilab.dao.mapper.system.FileManageMapper;
import com.brillilab.domain.enums.common.BoolEnum;
import com.brillilab.domain.enums.file.UploadStausEnum;
import com.brillilab.domain.po.system.FileManage;
import com.brillilab.service.core.system.IFileManageService;

import cn.hutool.core.collection.CollUtil;

/**
 * <p>
 * 文件管理 服务实现类
 * </p>
 *
 * @author WuMenghao
 * @since 2019-05-10
 */
@Service
public class FileManageServiceImpl implements IFileManageService {

    @Resource
    private FileManageMapper fileManageMapper;
    @Resource
    private OssUtils ossUtil;

    @Override
    public FileManage insert(FileManage entity) {
        Integer insert = fileManageMapper.insert(entity);
        Assert.isTrue(insert == 1, "添加失败");
        return entity;
    }

    @Override
    public List<FileManage> getAutoFileListByExperimentIdList(List<Long> experimentIdList) {
        LambdaQueryWrapper<FileManage> query = new LambdaQueryWrapper<>();
        query.in(FileManage::getReferDataId, experimentIdList);
        query.isNotNull(FileManage::getPath);//path空值过滤
        query.eq(FileManage::getIsDelete, false);//剔除已删除的文件
//        query.eq(FileManage::getIsDownload, 0);//剔除已下载的文件
        query.eq(FileManage::getUploadStatus,2);

        //过滤超过30天有效期的附件
        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date());
        cal.add(Calendar.DAY_OF_MONTH,-30);
        query.between(FileManage::getCallbackTime,cal,new Date());
        query.orderByAsc(FileManage::getCallbackTime);
        query.orderByDesc(FileManage::getAttachType);
        //实验结果文件
        query.between(FileManage::getAttachType, OssFileEnum.AnalyzeDataFile.getKey(), OssFileEnum.AnalyzeDataFileThumbnail.getKey());
        return fileManageMapper.selectList(query);
    }

    @Override
    public List<FileManage> getAutoFileListByLabId(Long labId) {
        LambdaQueryWrapper<FileManage> query = new LambdaQueryWrapper<>();
        query.eq(FileManage::getLabId, labId);
        query.isNotNull(FileManage::getPath);//path空值过滤
        query.eq(FileManage::getIsDelete, false);//剔除已删除的文件
//        query.eq(FileManage::getIsDownload, 0);//剔除已下载的文件
        query.eq(FileManage::getUploadStatus,2);

        //过滤超过30天有效期的附件
        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date());
        cal.add(Calendar.DAY_OF_MONTH,-30);
        //query.ge(FileManage::getCallbackTime,cal);
        query.between(FileManage::getCallbackTime,cal,new Date());
        //实验结果文件
        query.between(FileManage::getAttachType, OssFileEnum.AnalyzeDataFile.getKey(), OssFileEnum.AnalyzeDataFileThumbnail.getKey());
        query.orderByAsc(FileManage::getCallbackTime);
        query.orderByDesc(FileManage::getAttachType);
        return fileManageMapper.selectList(query);
    }

    @Override
    public List<FileManage> listByIdList(List<Long> attachIds) {
        LambdaQueryWrapper<FileManage> query = new LambdaQueryWrapper<>();
        query.in(FileManage::getId, attachIds);
        return fileManageMapper.selectList(query);
    }

    @Override
    public List<FileManage> selectList(OssFileEnum fileEnum, Long referDataId) {
        LambdaQueryWrapper<FileManage> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FileManage::getIsDelete, BoolEnum.FALSE.getValue());
        wrapper.eq(FileManage::getAttachType, fileEnum.getKey());
        wrapper.eq(FileManage::getReferDataId, referDataId);
        return fileManageMapper.selectList(wrapper);
    }

    @Override
    public Long uploadCallBack(JSONObject jsonObject) {
        if (jsonObject != null) {
            //自定义参数
            Integer attachType = jsonObject.getInteger("attachType");
            String fileName = jsonObject.getString("fileName");
            String previewImg = jsonObject.getString("previewImg");
            Integer audioLength = jsonObject.getInteger("audioLength");

            Assert.isTrue(!fileName.contains("%"),"文件名包含特殊字符，请核实！");

            //系统参数
            String bucket = jsonObject.getString("bucket");
            String filePath = jsonObject.getString("filePath");
            String mimeType = jsonObject.getString("mimeType");
            Long fileSize = jsonObject.getLong("size");


            int fileType = 0;//文件类型(0文件，1音频，2视频，3图片)
            fileType = FileTypeUtil.getFileType(fileName);

            FileManage fileManage = new FileManage();
            fileManage.setAttachType(attachType);
            fileManage.setReferDataId(0L);
            fileManage.setName(fileName);
            fileManage.setBucketName(bucket);
            fileManage.setMimeType(mimeType);
            fileManage.setFileType(fileType);
            fileManage.setPath(filePath);
            fileManage.setSize(fileSize);
            fileManage.setUploadStatus(UploadStausEnum.Uploaded.getValue());
            fileManage.setAudioLength(audioLength);
            fileManage.setPreviewImg(previewImg);
            fileManage.setUpdateTime(new Date());
            //上传成功更新回调时间
            fileManage.setCallbackTime(new Date());
            fileManage.setCallbackInfo(jsonObject.toJSONString());

            FileManage fileModel = insert(fileManage);
            return fileModel.getId();
        }
        return 0l;
    }

    @Override
    public List<FileManage> selectList(Long[] ids) {
    	Assert.isTrue(ids!=null && ids.length>0, "参数缺失！");
    	return this.selectListByIds(CollUtil.toList(ids));
    }
    
    @Override
	public List<FileManage> selectListByIds(List<Long> ids) {
		Assert.isTrue(CollUtil.isNotEmpty(ids), "参数缺失！");
        LambdaQueryWrapper<FileManage> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(FileManage::getId, ids);
        return fileManageMapper.selectList(wrapper);
	}

    /**
     * 根据附件类型获取文件列表
     *
     * @param attachType
     * @return
     */
    @Override
    public List<FileManage> getFileListByAttachType(Integer attachType) {
        LambdaQueryWrapper<FileManage> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FileManage::getAttachType, attachType);
        wrapper.eq(FileManage::getUploadStatus, UploadStausEnum.Uploaded.getValue());
        wrapper.eq(FileManage::getIsDelete, false);
        return fileManageMapper.selectList(wrapper);
    }

    /**
     * 根据数据关联id获取文件列表
     *
     * @param referDataId
     * @return
     */
    @Override
    public List<FileManage> getFileListByReferDataId(Integer referDataId) {
        LambdaQueryWrapper<FileManage> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FileManage::getReferDataId, referDataId);
        wrapper.eq(FileManage::getUploadStatus, UploadStausEnum.Uploaded.getValue());
        wrapper.eq(FileManage::getIsDelete, false);
        return fileManageMapper.selectList(wrapper);
    }

    /**
     * 获取未上传文件
     *
     * @param attachType
     * @param bucketName
     * @param fileName
     * @return
     */
    @Override
    public FileManage selectUnUpload(Integer attachType, String bucketName, String fileName) {
        LambdaQueryWrapper<FileManage> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FileManage::getAttachType, attachType);
        wrapper.eq(FileManage::getBucketName, bucketName);
        wrapper.eq(FileManage::getUploadStatus, UploadStausEnum.UnUpload.getValue());
        List<FileManage> fileManageList = fileManageMapper.selectList(wrapper);
        return fileManageList != null && fileManageList.size() > 0 ? fileManageList.get(0) : null;
    }

    @Override
    public List<FileManage> insertBatch(List<FileManage> fileManages) {
        Assert.isTrue(CollectionUtils.isNotEmpty(fileManages), "uploadFiles can not be empty!");
        Integer rs = fileManageMapper.insertBarth(fileManages);
        Assert.isTrue(rs == fileManages.size(), "操作失败！");
        return fileManages;
    }

    @Override
    public boolean updateById(FileManage fileManage) {
        int b = fileManageMapper.updateById(fileManage);
        return b == 1 ? true : false;
    }

    @Override
    public boolean deleteById(Long id) {
        //int b = fileManageMapper.deleteById(id);
        FileManage fileManage = fileManageMapper.selectById(id);
        if (fileManage == null) {
            return false;
        } else {
            //标记删除
            fileManage.setIsDelete(true);
            return fileManageMapper.updateById(fileManage) > 0 ? true : false;
        }
    }

    @Override
    public FileManage selectById(Long id) {
        FileManage fileManage = fileManageMapper.selectById(id);
        return fileManage;
    }

    @Override
    public void relevanceBatch(Long[] fileIds, Long referDataId, OssFileEnum fileEnum, Long labId, Long userId) {
        if (ArrayUtils.isNotEmpty(fileIds)) {
            FileManage fileManage = new FileManage();
            fileManage.setReferDataId(referDataId);
            fileManage.setAttachType(fileEnum.getKey());
            fileManage.setIsEncrypt(fileEnum.getIsEncrypt());
            fileManage.setLabId(labId);
            fileManage.setUserId(userId);
            fileManage.setUploadStatus(UploadStausEnum.Uploaded.getValue());
            LambdaQueryWrapper<FileManage> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(FileManage::getId, Arrays.asList(fileIds));
            fileManageMapper.update(fileManage, wrapper);
        }

    }

    @Override
    public List<FileManage> insertBatch(List<FileManage> fileList, Long referDataId, OssFileEnum fileEnum, Long labId,
                                        Long userId) {
        List<FileManage> list = new ArrayList<FileManage>();
        if (!CollectionUtils.isEmpty(fileList)) {
            fileList.forEach(fileManage -> {
                if (fileManage.getId() == null) {
                    fileManage.setReferDataId(referDataId);
                    fileManage.setAttachType(fileEnum.getKey());
                    fileManage.setIsEncrypt(fileEnum.getIsEncrypt());
                    fileManage.setLabId(labId);
                    fileManage.setUserId(userId);
                    fileManage.setBucketName(ossUtil.getBucketName(fileEnum.getKey()));
                    fileManage.setUploadStatus(UploadStausEnum.Uploading.getValue());
                    int insert = fileManageMapper.insert(fileManage);
                    if (insert == 1)
                        list.add(fileManage);
                }
            });
        }
        return list;
    }

    @Override
    public List<FileManage> getFileList(String urls) {
        List<FileManage> list = new ArrayList<>();
        if (StringUtils.isNotBlank(urls)) {
            List<String> urlList = Arrays.asList(urls.split("\\*#\\*"));
            for (String url : urlList) {
                String[] array = url.split("/");
                if (array.length > 1) {
                    FileManage file = new FileManage();
                    String fileName = array[array.length - 1];
					fileName = fileName.split("\\?")[0];
					if (fileName.split("\\.").length == 1) {
                        fileName = fileName + ".pdf";
                    }
                    file.setName(fileName);
                    if (!url.trim().startsWith("http")) {
						url = "https://labinone-public.oss-cn-hangzhou.aliyuncs.com" + url;
                    }
                    file.setPath(url.trim());
                    file.setFileType(0);
                    list.add(file);
                }
            }
        }
        return list;
    }

    @Override
    @Transactional
    public List<FileManage> insertBatch(String urls, Long referDataId, OssFileEnum fileEnum, Long labId, Long userId) {
        List<FileManage> list = new ArrayList<FileManage>();
        if (StringUtils.isNotBlank(urls)) {
            List<FileManage> files = getFileList(urls);
            if (!CollectionUtils.isEmpty(files)) {
                files.forEach(fileManage -> {
                    fileManage.setReferDataId(referDataId);
                    fileManage.setAttachType(fileEnum.getKey());
                    fileManage.setIsEncrypt(fileEnum.getIsEncrypt());
                    fileManage.setLabId(labId);
                    fileManage.setUserId(userId);
                    fileManage.setBucketName(ossUtil.getBucketName(fileEnum.getKey()));
                    fileManage.setUploadStatus(UploadStausEnum.Uploaded.getValue());
                    int insert = fileManageMapper.insert(fileManage);
                    if (insert == 1)
                        list.add(fileManage);
                });
            }
        }
        return list;
    }

    @Override
    public List<FileManage> selectList(OssFileEnum fileEnum, List<Long> referDatdIdList) {
        LambdaQueryWrapper<FileManage> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FileManage::getIsDelete, BoolEnum.FALSE.getValue());
        wrapper.eq(FileManage::getAttachType, fileEnum.getKey());
        wrapper.in(FileManage::getReferDataId, referDatdIdList);
        return fileManageMapper.selectList(wrapper);
    }

    @Override
    public boolean saveFilePublicUrlList(List<String> urlList, Long dataId, OssFileEnum fileEnum) {
        List<FileManage> fileList = new ArrayList<>();
        for (String url : urlList) {
            FileManage file = new FileManage();
            file.setAttachType(fileEnum.getKey());
            String[] nameArr = url.split("/");
            file.setName(nameArr[nameArr.length - 1]);
            file.setPath(url.trim());
            file.setFileType(0);
            file.setReferDataId(dataId);
            file.setUploadStatus(UploadStausEnum.Uploaded.getValue());
            file.setBucketName(ossUtil.getBucketName(fileEnum.getKey()));
            file.setAudioLength(0);
            file.setSize(0L);
            file.setIsEncrypt(false);
            fileList.add(file);
        }
        return fileManageMapper.insertBarth(fileList) > 0;
    }

    @Override
    public void deleteByAttachTypeAndReferDataId(OssFileEnum fileEnum, Long referDataId) {
        LambdaQueryWrapper<FileManage> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FileManage::getAttachType,fileEnum.getKey());
        wrapper.eq(FileManage::getReferDataId,referDataId);
        FileManage entity = new FileManage();
        entity.setIsDelete(true);
        fileManageMapper.update(entity, wrapper);
    }

    @Override
    public void deleteByAttachTypeAndReferDataId(OssFileEnum fileEnum, Long referDataId, Long fileManageId) {
        LambdaQueryWrapper<FileManage> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FileManage::getAttachType,fileEnum.getKey());
        wrapper.eq(FileManage::getReferDataId,referDataId);
        wrapper.ne(FileManage::getId,fileManageId);
        FileManage entity = new FileManage();
        entity.setIsDelete(true);
        fileManageMapper.update(entity, wrapper);
    }

    @Override
    public List<Long> selectFileIdArray(OssFileEnum fileEnum, Long referDataId) {
        return fileManageMapper.selectIdArray(fileEnum.getKey(), referDataId);
    }

    @Override
    public int deleteBatchById(Long[] fileIds) {
        return fileManageMapper.deleteBatchIds(Arrays.asList(fileIds));

    }

	@Override
	public int selectCount(List<Integer> fileEnums, List<Long> referDataIds) {
		  LambdaQueryWrapper<FileManage> query = new LambdaQueryWrapper<>();
	        query.in(FileManage::getReferDataId, referDataIds);
	        query.in(FileManage::getAttachType, fileEnums);
	        query.isNotNull(FileManage::getPath);
	        query.eq(FileManage::getIsDelete, false);
		return fileManageMapper.selectCount(query);
	}

	@Override
	public List<FileManage> selectList(List<Integer> fileEnums, List<Long> referDataIds, Boolean isDelete) {
		 LambdaQueryWrapper<FileManage> query = new LambdaQueryWrapper<>();
	        query.in(FileManage::getReferDataId, referDataIds);
	        query.in(FileManage::getAttachType, fileEnums);
	        query.isNotNull(FileManage::getPath);
	        if(isDelete!=null)
	        	query.eq(FileManage::getIsDelete, isDelete);
		return fileManageMapper.selectList(query);
	}

	@Override
	public List<FileManage> selectList(List<Integer> fileEnums) {
		LambdaQueryWrapper<FileManage> query = new LambdaQueryWrapper<>();
        query.in(FileManage::getAttachType, fileEnums);
        query.isNotNull(FileManage::getPath);
        query.eq(FileManage::getIsDelete, BoolEnum.FALSE.getValue());
//        query.eq(FileManage::getIsDownload, BoolEnum.FALSE.getValue());
        return fileManageMapper.selectList(query);
	}

	@Override
	public void updateIsDownload(List<Long> fileIds) {
		LambdaQueryWrapper<FileManage> query = new LambdaQueryWrapper<>();
        query.in(FileManage::getId, fileIds);
        query.eq(FileManage::getIsDelete, BoolEnum.FALSE.getValue());
//        query.eq(FileManage::getIsDownload, BoolEnum.FALSE.getValue());
        FileManage file = new FileManage();
//        file.setIsDownload(BoolEnum.TRUE.getValue());
        file.setUpdateTime(new Date());
        fileManageMapper.update(file, query);
	}

	
}
